#!/bin/sh /etc/rc.common
# Created By [CTCGFW]Project OpenWRT
# https://github.com/project-openwrt

START=89
STOP=10

NAME="unblockneteasemusic"

uci_get_by_type() {
	local "ret"
	ret="$(uci get "$NAME".@"$1"[0]."$2" 2>/dev/null)"
	echo "${ret:=$3}"
}

uci_get_by_name() {
	local "index"
	index=0
	if [ -n "$4" ]; then
		index="$4"
	fi
	ret="$(uci get "$NAME".@"$1"["${index}"]."$2" 2>/dev/null)"
	echo "${ret:=$3}"
}

lan_addr="$(uci get network.lan.ipaddr)"

enable="$(uci_get_by_type "unblockneteasemusic" "enable" "0")"

music_source="$(uci_get_by_type "unblockneteasemusic" "music_source" "default")"
neteasemusic_cookie="$(uci_get_by_type "unblockneteasemusic" "neteasemusic_cookie")"
qq_cookie="$(uci_get_by_type "unblockneteasemusic" "qq_cookie")"
youtube_key="$(uci_get_by_type "unblockneteasemusic" "youtube_key")"

enable_flac="$(uci_get_by_type "unblockneteasemusic" "enable_flac" "0")"
[ "${enable_flac}" -eq "1" ] && flag_arg="ENABLE_FLAC=true"

endpoint_url="$(uci_get_by_type "unblockneteasemusic" "endpoint_url" "http://music.163.com")"
hijack_ways="$(uci_get_by_type "unblockneteasemusic" "hijack_ways" "use_ipset")"

auto_update="$(uci_get_by_type "unblockneteasemusic" "auto_update" "1")"
update_time="$(uci_get_by_type "unblockneteasemusic" "update_time" "3")"

http_port="$(uci_get_by_type "unblockneteasemusic" "http_port" "5200")"
https_port="$(uci_get_by_type "unblockneteasemusic" "https_port" "5201")"

keep_core_when_upgrade="$(uci_get_by_type "unblockneteasemusic" "keep_core_when_upgrade")"
[ "$(uci_get_by_type "unblockneteasemusic" "pub_access")" = "1" ] && addr="0.0.0.0" || addr="${lan_addr}"
[ "$(uci_get_by_type "unblockneteasemusic" "strict_mode")" = "1" ] && strict_mode="-s"

netease_server_ip="$(uci_get_by_type "unblockneteasemusic" "netease_server_ip")"
[ -n "${netease_server_ip}" ] && netease_server_ip="-f ${netease_server_ip}"
proxy_server_ip="$(uci_get_by_type "unblockneteasemusic" "proxy_server_ip")"
[ -n "${proxy_server_ip}" ] && proxy_server_ip="-u ${proxy_server_ip}"

self_issue_cert_crt="$(uci_get_by_type "unblockneteasemusic" "self_issue_cert_crt")"
self_issue_cert_key="$(uci_get_by_type "unblockneteasemusic" "self_issue_cert_key")"

set_ipset()
{
	if [ "${set_type}" = "start" ]; then
		mkdir -p "/tmp/dnsmasq.d"
		rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
		cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
dhcp-option=252,http://${lan_addr}:${http_port}/proxy.pac
ipset=/.music.163.com/neteasemusic
ipset=/interface.music.163.com/neteasemusic
ipset=/interface3.music.163.com/neteasemusic
ipset=/apm.music.163.com/neteasemusic
ipset=/apm3.music.163.com/neteasemusic
ipset=/clientlog.music.163.com/neteasemusic
ipset=/clientlog3.music.163.com/neteasemusic
		EOF
		/etc/init.d/dnsmasq reload > "/dev/null" 2>&1

		if ! ipset list "acl_neteasemusic_http" > "/dev/null"; then ipset create "acl_neteasemusic_http" hash:ip; fi
		if ! ipset list "acl_neteasemusic_https" > "/dev/null"; then ipset create "acl_neteasemusic_https" hash:ip; fi
		ip_addr_num="$(uci show "unblockneteasemusic" | grep -c "filter_mode")"
		let ip_addr_num="ip_addr_num-1"
		[ "${ip_addr_num}" -ge "0" ] && for i in $(seq 0 "${ip_addr_num}")
		do
			ip_addr="$(uci_get_by_name "acl_rule" "ip_addr" "" "$i")"
			filter_mode="$(uci_get_by_name "acl_rule" "filter_mode" "" "$i")"
			case "${filter_mode}" in
			"disable_http")
				ipset -! add "acl_neteasemusic_http" "${ip_addr}"
				;;
			"disable_https")
				ipset -! add "acl_neteasemusic_https" "${ip_addr}"
				;;
			"disable_all")
				ipset -! add "acl_neteasemusic_http" "${ip_addr}"
				ipset -! add "acl_neteasemusic_https" "${ip_addr}"
				;;
			esac
		done

		if ! ipset list "neteasemusic" > "/dev/null"; then ipset create "neteasemusic" hash:ip; fi
		curl --retry "5" --retry-delay "3" -s "http://httpdns.n.netease.com/httpdns/v2/d?domain=music.163.com,interface.music.163.com,interface3.music.163.com,apm.music.163.com,apm3.music.163.com,clientlog.music.163.com,clientlog3.music.163.com" |grep -Eo '[0-9]+?\.[0-9]+?\.[0-9]+?\.[0-9]+?' |sort |uniq |awk '{print "ipset add neteasemusic "$1}' |bash > "/dev/null" 2>&1
		iptables -t "nat" -N "netease_cloud_music"
		iptables -t "nat" -A "netease_cloud_music" -d "0.0.0.0/8" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -d "10.0.0.0/8" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -d "127.0.0.0/8" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -d "169.254.0.0/16" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -d "172.16.0.0/12" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -d "192.168.0.0/16" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -d "224.0.0.0/4" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -d "240.0.0.0/4" -j "RETURN"
		iptables -t "nat" -A "netease_cloud_music" -p "tcp" -m "set" ! --match-set "acl_neteasemusic_http" "src" --dport "80" -j "REDIRECT" --to-ports "${http_port}"
		iptables -t "nat" -A "netease_cloud_music" -p "tcp" -m "set" ! --match-set "acl_neteasemusic_https" "src" --dport "443" -j "REDIRECT" --to-ports "${https_port}"
		iptables -t "nat" -I "PREROUTING" -p "tcp" -m "set" --match-set "neteasemusic" "dst" -j "netease_cloud_music"
		[ -z "$(iptables -t "nat" -L "KOOLPROXY" | grep "UnblockMusic" | sed 's/\/.*//')" ] && iptables -t "nat" -I "KOOLPROXY" -m "set" --match-set "neteasemusic" "dst" -j "RETURN" -m "comment" --comment "KP for UnblockMusic"

		mkdir -p "/var/etc/"
		echo "/etc/init.d/unblockneteasemusic restart" > "/var/etc/unblockneteasemusic.include"
	elif [ "${set_type}" = "stop" ]; then
		iptables -t "nat" -D "PREROUTING" -p "tcp" -m set --match-set "neteasemusic" "dst" -j "netease_cloud_music"
		iptables -t "nat" -D "KOOLPROXY" -m "set" --match-set "neteasemusic" "dst" -j "RETURN" -m "comment" --comment "KP for UnblockMusic"
		iptables -t "nat" -F "netease_cloud_music"
		iptables -t "nat" -X "netease_cloud_music"
		ipset destroy "neteasemusic"
		ipset destroy "acl_neteasemusic_http"
		ipset destroy "acl_neteasemusic_https"

		echo "" > "/var/etc/unblockneteasemusic.include"
		rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
		/etc/init.d/dnsmasq reload > "/dev/null" 2>&1
	fi
}

set_hosts()
{
	if [ "${set_type}" = "start" ]; then
		mkdir -p "/tmp/dnsmasq.d"
		rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
		cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
dhcp-option=252,http://${lan_addr}:${http_port}/proxy.pac
address=/music.163.com/${lan_addr}
address=/interface.music.163.com/${lan_addr}
address=/interface3.music.163.com/${lan_addr}
address=/apm.music.163.com/${lan_addr}
address=/apm3.music.163.com/${lan_addr}
address=/clientlog.music.163.com/${lan_addr}
address=/clientlog3.music.163.com/${lan_addr}
address=/music.httpdns.c.163.com/0.0.0.0
		EOF
		/etc/init.d/dnsmasq reload > "/dev/null" 2>&1

		ip route add "223.252.199.10" dev lo
	elif [ "${set_type}" = "stop" ]; then
		rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf"
		/etc/init.d/dnsmasq reload > "/dev/null" 2>&1

		ip route del "223.252.199.10"
	fi
}

set_ports()
{
	if [ "${set_type}" = "start" ]; then
		iptables -I "INPUT" -p "tcp" --dport "${http_port}" -j "ACCEPT"
		iptables -I "INPUT" -p "tcp" --dport "${https_port}" -j "ACCEPT"

		mkdir -p "/var/etc/"
		echo "/etc/init.d/unblockneteasemusic restart" > "/var/etc/unblockneteasemusic.include"
	elif [ "${set_type}" = "stop" ]; then
		iptables -D "INPUT" -p "tcp" --dport "${http_port}" -j "ACCEPT"
		iptables -D "INPUT" -p "tcp" --dport "${https_port}" -j "ACCEPT"

		echo "" > "/var/etc/unblockneteasemusic.include"
	fi
}

start()
{
	stop

	[ "${enable}" -ne "1" ] && exit 0

	[ ! -e "/usr/share/unblockneteasemusic/core/app.js" ] && { rm -f "/usr/share/unblockneteasemusic/local_ver"; bash "/usr/share/unblockneteasemusic/update.sh" "update_core_non_restart"; }
	[ ! -e "/usr/share/unblockneteasemusic/core/app.js" ] && { echo "Core Not Found, please download it before starting." >> "/tmp/unblockneteasemusic.log"; exit 1; }

	[ -n "${neteasemusic_cookie}" ] && {
		ub_cookie_line="$(sed -n -e "/netease.path.includes('song\/enhance')/=" "/usr/share/unblockneteasemusic/core/src/hook.js")";
		[ -n "${ub_cookie_line}" ] && { let ub_cookie_endline="${ub_cookie_line}+6"; sed -i "${ub_cookie_line},${ub_cookie_endline}d" "/usr/share/unblockneteasemusic/core/src/hook.js"; }
		sed -i "/netease.path == '\/api\/song\/enhance\/download\/url'/i\\\t\\t\\t\\tif (netease.path.includes('song\/enhance')) {" "/usr/share/unblockneteasemusic/core/src/hook.js";
		sed -i "/if (netease.path.includes('song\/enhance')) {/a\\\t\\t\\t\\t\\treq.headers.cookie = [" "/usr/share/unblockneteasemusic/core/src/hook.js";
		sed -i "/req.headers.cookie = \[/a\\\t\\t\\t\\t\\t\\t'MUSIC_U=${neteasemusic_cookie}'," "/usr/share/unblockneteasemusic/core/src/hook.js";
		sed -i "/'MUSIC_U=${neteasemusic_cookie}',/a\\\t\\t\\t\\t\\t\\treq.headers.cookie.replace(\/\\\s*MUSIC_\\\w=[^\\\s;]+;*\/g, '')" "/usr/share/unblockneteasemusic/core/src/hook.js";
		sed -i "/req.headers.cookie.replace(\/\\\s\\*MUSIC_\\\w=[^\\\s;]\\+/a\\\t\\t\\t\\t\\t].filter(line => line).join('; ')" "/usr/share/unblockneteasemusic/core/src/hook.js";
		sed -i "/].filter(line => line).join('; ')/a\\\t\\t\\t\\t}\\n" "/usr/share/unblockneteasemusic/core/src/hook.js";
}
	[ -n "${qq_cookie}" ] && {
		qq_cookie_line="$(awk "/'cookie':/{print NR}" "/usr/share/unblockneteasemusic/core/src/provider/qq.js")";
		sed -i "${qq_cookie_line}d" "/usr/share/unblockneteasemusic/core/src/provider/qq.js";
		sed -i -e "${qq_cookie_line}i \\\t'cookie': '${qq_cookie}'" "/usr/share/unblockneteasemusic/core/src/provider/qq.js";
}
	[ -n "${youtube_key}" ] && {
		sed -i '/const key = /d' "/usr/share/unblockneteasemusic/core/src/provider/youtube.js";
		sed -i -e "1i const key = '${youtube_key}'" "/usr/share/unblockneteasemusic/core/src/provider/youtube.js";
}

	{ [ -f "${self_issue_cert_crt}" ] && [ "${self_issue_cert_crt}" != "/usr/share/unblockneteasemusic/core/server.crt" ]; } && { ln -sf "${self_issue_cert_crt}" "/usr/share/unblockneteasemusic/core/server.crt"; sed -i "/${self_issue_cert_crt//\//\\/}/d"; echo "${self_issue_cert_crt}" >> "/etc/sysupgrade.conf"; }
	{ [ -f "${self_issue_cert_key}" ] && [ "${self_issue_cert_key}" != "/usr/share/unblockneteasemusic/core/server.key" ]; } && { ln -sf "${self_issue_cert_key}" "/usr/share/unblockneteasemusic/core/server.key"; sed -i "/${self_issue_cert_key//\//\\/}/d"; echo "${self_issue_cert_key}" >> "/etc/sysupgrade.conf"; }

	[ "${hijack_ways}" = "use_hosts" ] && { http_port="80"; https_port="443"; }
	if [ "${music_source}" = "default" ]; then
		nohup env ${flag_arg} node "/usr/share/unblockneteasemusic/core/app.js" -a "${addr}" -p "${http_port}":"${https_port}" -e "${endpoint_url}" ${netease_server_ip} ${proxy_server_ip} ${strict_mode} >> "/tmp/unblockneteasemusic.log" 2>&1 &
	else
		nohup env ${flag_arg} node "/usr/share/unblockneteasemusic/core/app.js" -a "${addr}" -p "${http_port}":"${https_port}" -o ${music_source} -e "${endpoint_url}" ${netease_server_ip} ${proxy_server_ip} ${strict_mode} >> "/tmp/unblockneteasemusic.log" 2>&1 &
	fi

	set_type="start"
	if [ "${hijack_ways}" = "use_ipset" ]; then
		set_ipset > "/dev/null" 2>&1
	elif [ "${hijack_ways}" = "use_hosts" ]; then
		set_hosts > "/dev/null" 2>&1
	fi

	[ "$(uci_get_by_type "unblockneteasemusic" pub_access)" = "1" ] && set_ports > "/dev/null" 2>&1

	sed -i '/unblockneteasemusic/d' /etc/crontabs/root
	[ "${auto_update}" -eq "1" ] && echo "0 ${update_time} * * * /usr/share/unblockneteasemusic/update.sh update_core" >> "/etc/crontabs/root"
	echo "*/5 * * * * /usr/share/unblockneteasemusic/log_check.sh" >> "/etc/crontabs/root"
	/etc/init.d/cron restart > "/dev/null" 2>&1
}

stop()
{
	{ ps |grep "unblockneteasemusic" |grep "app.js" |grep -v "grep" |awk '{print $1}' |xargs kill -9; } > "/dev/null" 2>&1

	sed -i '/unblockneteasemusic/d' "/etc/crontabs/root"
	/etc/init.d/cron restart > "/dev/null" 2>&1

	sed -i '/unblockneteasemusic\/core/d;/unblockneteasemusic\/local_ver/d' "/etc/sysupgrade.conf"
	[ "${keep_core_when_upgrade}" -eq "1" ] && { echo "/usr/share/unblockneteasemusic/core/" >> "/etc/sysupgrade.conf"; echo "/usr/share/unblockneteasemusic/local_ver" >> "/etc/sysupgrade.conf"; }

	rm -f "/tmp/unblockneteasemusic.log"

	set_type="stop"
	set_ipset > "/dev/null" 2>&1
	set_hosts > "/dev/null" 2>&1
	set_ports > "/dev/null" 2>&1
}
